// joypar js
// =? getValueByPath
// =10 Feature
var K = {
	debug : false,
	version : '0.1',
	init : function() {
		var me = this;
		// Number
		me.extend(Number.prototype, (function(scope) {
			// 四写五入
			function toFixed(exact) {
				var add = 0, s, s1 = this + "", start = s1.indexOf(".");
				if (s1.substr(start + exact + 1, 1) >= 5) {
					add = 1;
				}
				var temp = Math.pow(10, exact);
				s = Math.floor(this * temp) + add;
				return s / temp;
			}

			return {
				toFixed : toFixed
			};
		})());

		// Math
		me.extend(Math, (function(scope) {
			// 随即数
			function randomRange(min, max, exact) {
				if (arguments.length === 0) {
					return Math.random();
				} else if (arguments.length === 1) {
					max = min;
					min = 0;
				}
				var range = min + (Math.random() * (max - min));
				return exact === void (0) ? Math.round(range) : range.toFixed(exact);
			}
			return {
				randomRange : randomRange
			};
		})());

		// String
		me.extend(String.prototype, (function(scope) {
			function startWith(str) {
				return !me.isEmpty(str) && (this.indexOf(str) == 0);
			}

			return {
				startWith : startWith
			};
		})());
	},
	extend : function(target, conf) {
		if (target) {
			$.each(conf || {}, function(k, v) {
				target[k] = v;
			});
		}
	},
	trim : function(str) {
		return $.trim(str);
	},
	isBlank : function(str) { // '' || ' '
		return K.isEmpty(str) || K.trim(str).length == 0;
	},
	isEmpty : function(str) { // ''
		return !str || str.length == 0;
	},
	isNumber : function(value) {
		return /^-?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?$/.test(value);
	},

	// 随机字母A-Z,a-z
	// upper :
	// true : 返回大写
	// false : 返回小写
	randomString : function(num, upper) {
		var buf = [];
		var caseUseRandom = upper === undefined;
		upper = !!upper;
		for ( var i = 0; i < num; i++) {
			if (caseUseRandom) {
				upper = Math.randomRange(1, 2) % 2 == 0;
			}

			if (upper) {
				buf.push(String.fromCharCode(Math.randomRange(65, 90)));
			} else {
				buf.push(String.fromCharCode(Math.randomRange(97, 122)));
			}
		}
		return buf.join('');
	}
};
K.init();

K.currentTime = function() {
	return new Date().getTime();
};

K.randomUrl = function(url) {
	if (url.indexOf('?') == -1) {
		url += "?";
	} else {
		url += "&";
	}
	url += "ajax_current_time=" + K.currentTime();
	return url;
};
K.wrapIframe = function(config, ps) {
	var buf = [];
	if (typeof (config) == 'string') {
		config = {
			url : config
		};
	}

	if (ps) {
		$.extend(config.params = config.params || {}, ps);
	}

	config.id = config.id || "iframe_id_" + K.randomString(12, false);
	config.name = config.name || "iframe_name_" + K.randomString(12, false);
	config.url = config.url || "" + "?t=" + K.randomString(12, false);

	var params = [];
	$.each(config.params || {}, function(k, v) {
		params.push(k + "=" + v);
	});

	var url = config.url;
	if (url.indexOf("?") == -1) {
		url += "?";
	}

	if (params.length) {
		url += params.join("&");
	}

	buf.push("<iframe id='" + config.id + "' name='" + config.name + "'");
	buf.push(" frameborder='0'");
	buf.push(" src='" + url + "'");
	buf.push(" style='width:100%;height:100%;'");
	buf.push("></iframe>");

	return buf.join("");
};
K.createIframe = function(c) {
	var iframe = document.createElement("iframe");
	iframe.setAttribute("frameborder", "0");
	iframe.frameBorder = iframe.frameBorder || 0;

	iframe.style.border = "0px";
	iframe.style.width = "100%";
	iframe.style.height = "100%";
	iframe.src = c.src;

	// event.srcElement||event.target
	if (c.onload) {
		$(iframe).load(c.onload);
	}

	if (c.appendTo) {
		$(iframe).appendTo(c.appendTo);
	}

	return iframe;
};

/**
 * 值填充
 * 
 * @param {conf.data}
 *            数据
 * @param {conf.target}
 *            element目标,如form
 * @param {conf.fn}
 *            true:继续执行,false:continue
 */
K.autofill = function(config) {
	config = config || {};
	if (!config.data || !config.target) {
		return false;
	}
	var filter = config.filter;
	if (!filter || $.trim(filter).length == 0) {
		filter = "input,select,textarea";
	}

	var cb = config.fn || function() {
		return true;
	}, nullText = config.nullText || "&nbsp;", data = config.data;
	nullValue = config.nullValue || "not impl";

	var target = config.target;
	if (typeof (config.target) == "string") {
		target = document.getElementById(target); // use selector ?
	}

	$(filter, target || document).each(function(k, v) {
		var $this = $(this);
		if (!cb(v, $this, data)) { // next
			return true;
		}

		var key = $this.attr("key") || v.id || this.name;
		if (!key) {
			return true;
		}

		var value = K.getValueByPath(data, key);
		if (config.render) {
			value = config.render(key, value, data, $this);
		}

		// parse
		if (v.tagName == 'INPUT') {
			if (v.type == 'text' || v.type == 'hidden') {
				$this.val(value);
			} else if (v.type == "radio") {
				if (value == v.value) {
					var oldChecked = v.checked;
					$this.attr("checked", true);
					if (!oldChecked) {
						$this.change();
					}
				}
			} else if (v.type == "checkbox") {
				var oldChecked = v.checked, doFireChangeEvent = false;
				if (value == 1 || value === true || value == "on" || value == "yes" || value == "y") {
					$this.attr("checked", true);
					doFireChangeEvent = !oldChecked;
				} else {
					$this.attr("checked", false);
					doFireChangeEvent = oldChecked;
				}
				if (doFireChangeEvent) {
					$this.change();
				}
			}
		} else if (v.tagName == 'TEXTAREA') {
			$this.val(value);
		} else {
			$this.html(value || nullText);
		}
	});
};

// =getValueByPath
K.getValueByPath = function(data, path) {
	if (!data || !path) {
		return null;
	}

	var ps = path.split("."), lastValue = data, result = null;

	for ( var i = 0, len = ps.length; i < len; i++) {
		result = lastValue[ps[i]];
		if (!result) {
			break;
		}
		lastValue = result;
	}

	return result;
};

K.format = function(msg, data) {
	if (msg) {
		var template = new Ext.Template(msg);
		msg = template.applyTemplate(data);
	}
	return msg;
};
K.state = {
	update : "update",
	add : "add",
	del : "delete",
	view : "view"
};
K.loadMask = function(config, A1, A2) {
	K.loadMask.cache = K.loadMask.cache || {};
	var elem = null, target = false, msg = "正在处理请求,请您稍后......";
	if (typeof (config) == "string") {
		elem = config;
		if (typeof (A1) == "string") {
			msg = A1;
		}

		target = document.getElementById(elem);
		if (target == null) {
			msg = elem;
		}
	} else if (typeof (config) == "object") {
		elem = config.el || "document-body";
		msg = config.msg || msg;
	}

	elem = elem || "document-body";

	var x = y = 0;
	if (target) {
		x = target.getBoundingClientRect().left + document.documentElement.scrollLeft;
		y = target.getBoundingClientRect().top + document.documentElement.scrollTop;
	}

	var html = [];
	html.push("<div id='loading-mask-" + elem + "'></div>");
	html.push("<div id='loading-" + elem + "' >");
	html.push("<div id='loading-indicator-" + elem + "' >");
	html.push(msg);
	html.push("</div>");
	html.push("</div>");

	if (K.loadMask.cache[elem] != null) {
		this.removeMask(elem);
	}

	$(document.body.firstChild).before(html.join(""));
	$("#loading-" + elem).addClass("k-loading");
	$("#loading-indicator-" + elem).addClass("k-loading-indicator");

	K.loadMask.cache[elem] = elem;
	return $("#loading-mask-" + elem).addClass("k-loading-mask").css({
		"top" : y,
		"left" : x
	});
};

K.removeMask = function(elem, lazy) {
	if (typeof (elem) == "number") {
		setTimeout("K.removeMask()", elem);
		return;
	}

	if (typeof (lazy) == "number") {
		setTimeout("K.removeMask('" + elem + "')", lazy);
		return;
	}

	elem = elem || "document-body";
	$("#loading-mask-" + elem + ",#loading-" + elem).remove();
};

// =10 Feature
K.feature = {};
K.feature.fastjson = function() {
	function hasFeature(data, key) {
		return data[key].$ref || data[key].$lazy$XXXX$;
	}
	function convertRefValue(root) {
		// 检查是否转$ref换过
		var fastjson$ref = false;
		if (root instanceof Array) {
			$.each(root, function(i, v) {
				if (v.fastjson$ref === true) {
					fastjson$ref = true;
					return false;
				}
			});
		} else {
			fastjson$ref = root.fastjson$ref;
		}

		if (fastjson$ref === true) {
			return;
		}

		// var start = new Date().getTime();
		(function recursion(root, current, parent, parentRefKey) {
			$.each(current, function(key, value) {
				if (key == "$ref") {
					var s = "root" + current["$ref"].substr(1, current["$ref"].length);
					var $ref = eval(s);
					parent[parentRefKey] = $ref;
					return false;
				} else if (value && typeof (value) == "object") {
					// fix:当遍历$ref所在的对象时,$ref被替换成根,循环则以根继续循环
					// 返回 false直接退出该对象($ref所在对象)的循环
					return !(false === recursion(root, value, current, key));
				}
			});
		})(root, root, {}, "");
		// var end = new Date().getTime();
		// alert("递归耗时:" + (start - end));

		if (root instanceof Array) {
			$.each(root, function(i, v) {
				v.fastjson$ref = true;
			});
		} else {
			root.fastjson$ref = true;
		}
	}
	return {
		featureKeyMaps : {
			"$ref" : true,
			"$lazy$" : true
		},
		hasFeature : hasFeature,
		convertRefValue : convertRefValue
	};
};

K.fastjson = K.feature.fastjson();
K.josn = function(josn) {
}; // use extjs

// show error
K.showErrorMode = {
	ALERT : "alert"
};
K.SEM = K.showErrorMode;
K.registerShowErrorHandler = function(mode, fn) {
	K.showErrorHandlers = K.showErrorHandlers || {};
	K.showErrorHandlers[mode] = fn;
};
K.getShowErrorHandler = function(mode) {
	return K.showErrorHandlers[mode];
};
K.registerShowErrorHandler(K.SEM.ALERT, function(output) {
	if (output.hasError()) {
		var errorList = output.getErrorList(), msg = [];
		$.each(errorList, function(k, v) {
			msg.push(v.content);
		});
		if (msg.length) {
			alert(msg.join("\n"));
		}
	}
});

K.isOutputData = function(output) {
	if (output) {
		if (typeof output == "string") {
			return ("success".indexOf(output) != -1//
					&& "errorCount".indexOf(output) != -1 //
					&& "errorList".indexOf(output) != -1 //
					&& "messageList".indexOf(output) != -1 //
			&& "parameters".indexOf(output) != -1);
		} else {
			return (output.success != undefined //
					&& output.errorCount != undefined //
					&& output.errorList != undefined //
					&& output.messageList != undefined //
			&& output.parameters != undefined);
		}
	}
	return false;
};
K.Output = function(json) {
	json = typeof (json) == "string" ? K.json(json) : json;
	K.fastjson.convertRefValue(json);
	function Output(json) {
		this.defaultShowErrorMode = K.SEM.ALERT;
		this.json = json;
		this.model = this.json;
		this.parameters = this.json.parameters; // map
		this.setShowErrorMode = function(mode) {
			this.defaultShowErrorMode = mode;
		};
		this.success = function() {
			return this.json.success;
		};
		this.hasError = function() {
			return this.json.errorCount !== 0;
		};

		this.getErrorCount = function() {
			return this.json.errorCount;
		};
		this.getParameter = function(key) {
			if (!this.parameters) {
				return null;
			}
			return eval('this.parameters.' + key);
		};
		this.addParameter = function(key, value) {
			this.parameters[key] = value;
			return this;
		};
		this.getErrorList = function() {
			return this.json.errorList;
		};
		this.showError = function(mode) {
			if (!this.hasError()) {
				return false;
			}
			mode = mode || this.defaultShowErrorMode;
			K.getShowErrorHandler(mode)(this);
			return true;
		};
	}
	return new Output(json);
};

K.output = K.createOutput = function(data) {
	if (!data) {
		alert("创建一个Output对象失败，因为它是空的");
		return;
	}
	return new K.Output(data);
};
K.mockOutput = function(config) {
	var output = k.output(K.extend({
		errorCount : 0,
		errorList : [],
		messageList : [],
		parameters : {},
		success : true
	}, config));
	output.toJson = function() {
		if (Ext) {
			return Ext.encode(this.json);
		} else {
			alert("no impl!!!");
		}
	};
	return output;
};
K.Input = function(data) {
	this.map = $.extend(this, data);
	this.setParameter = function(key, value) {
		this.map.params = this.map.params || {};
		this.map.params[key] = value;
		return this;
	};
	this.getParameter = function(key) {
		return this.map.params ? this.map.params[key] : null;
	};
	this.set = function(key, value) {
		this.map[key] = value;
		return this;
	};
	this.get = function(key) {
		return this.map[key];
	};
};
K.input = K.createInput = function(data) {
	return new K.Input(data);
};

K.extend = function(obj, conf) {
	obj = obj || {};
	var objs = (obj instanceof Array) ? obj : [ obj ];
	for ( var i = 0; i < objs.length; i++) {
		$.extend(objs[i], conf);
	}
	return obj;
};

K.serializeJson = function(selector, filterEmpty) {
	var arr = $("input,textarea,select", selector).serializeArray(), j = {};
	$.each(arr, function(k, v) {
		if (v.value && (v.value = $.trim(v.value)).length != 0) {
			j[v.name] = $.trim(v.value);
		}
	});
	return j;
};
/**
 * 把表单数据转成JSON数据格式
 */
K.formToJson = function(selector, filterEmpty) {
	var arr = $("input,textarea,select", selector).serializeArray(), j = {};
	$.each(arr, function(k, v) {
		if (v.value && (v.value = $.trim(v.value)).length != 0) {
			j[v.name] = $.trim(v.value);
		}
	});
	return j;
};

K.getIframe = function(parentSelector, id) {
	var p = null;
	parentSelector = parentSelector || document;
	if (!(parentSelector instanceof $)) {
		p = $(parentSelector);
	}

	var $iframes = $("iframe" + (id ? " " + id : ""), p || document);
	if ($iframes.length) {
		var iframe = $iframes[0];
		iframe.wind = iframe.contentWindow || iframe.contentDocument;
		iframe.doc = iframe.wind.document;
		iframe.getIframe = (function(iframe) {
			return function(id) {
				return K.getIframe(iframe.doc, id);
			};
		})(iframe);
		return iframe;
	}
	return null;
};

/**
 * 调用一个服务 <br>
 * 
 * @param url
 *            后台请求地址
 * @param input
 *            输入参数对象, 如果传递参数请设置input的data属性
 */
K.service = function(url, input) {
	if (typeof url == "string") {
		input = input || {};
		input.url = url;
	} else {
		input = url || {};
	}
	if (K.isBlank(input.url)) {
		K.err("请输入URL");
		return;
	}
	K.post(input);
};
/**
 * 提交POST请求
 */
K.post = function(options) {
	if (!options.url) {
		alert("请输入提交的URL");
		return;
	}
	if (!options.form) {
		K.ajax(K.extend({
			type : "POST"
		}, options));
	} else {
		K.ajaxSubmit(options);
	}
};
K.ajaxSubmit = function ajaxForm(options) {
	if (!options.form) {
		alert("找不到提交的表单");
		return;
	}

	if (!options.url) {
		alert("请输入提交的URL");
		return;
	}

	var defautOptions = {
		type : "POST",
		beforeSubmit : function(a, jqForm, op) {
			return jqForm.valid();
		},
		clearForm : false,
		resetForm : false,
		timeout : 3600 * 1000
	};

	$.extend(defautOptions, options);

	var form = options.form; // use ID
	if (typeof (form) == "string") {
		form = form.indexOf("#") == 0 ? form : "#" + form;
		if (options.scope) {
			form = $(form, scope);
		} else {
			form = $(form);
		}
	} else if (!(form instanceof $)) {
		form = $(form);
	}

	form.ajaxSubmit(defautOptions);
	return;
};
K.validate = function(selector, options) {
	options.success = options.success || function(label) {
		label.addClass("checked");
	};
	var validator = $(selector).validate(options);
	return validator;
};

K.$import = function() {
	var config = K._getloadParams(arguments);
	window.loadedJsHash = window.loadedJsHash || {};
	if (window.loadedJsHash[config.url] && !config.alway === true) {
		return;
	}
	window.loadedJsHash[config.url] = true;
	K.loadjs(config);
};
K.loadjs = function() {
	config = K._getloadParams(arguments);
	var options = $.extend({
		type : "GET",
		async : false,
		scriptCharset : "utf-8",
		success : function(ignore) {
			// alert(ignore);
		},
		error : function() {
			alert("未能成功加载" + this.url);
		}
	}, config);

	options.dataType = "script";
	$.ajax(options);
};
K._getloadParams = function(args) {
	var config = args[0];

	if (typeof (config) == "string") {
		config = {
			url : config
		};
		if (args[1]) {
			config.success = args[1];
			if (args[2]) {
				config.error = args[2];
			}
		}
	}

	return config;
};

K.getObjectMsg = function(o) {
	if (!o) {
		return "";
	}

	var msg = [];
	for ( var p in o) {
		msg.push(p + ":" + o[p]);
	}

	return msg;
};

K.ajax = function(options) {
	options.url = K.randomUrl(options.url);
	options.data = K.extend(options.data || {}, options.params || {});
	$.ajax(options);
};
K.syncAjax = function(options) {
	if (typeof options == "string") {
		options = {
			url : options
		};
	}
	var rs = null;
	options.async = false;
	options.success = options.success || function(output) {
		output = K.json(output);
		rs = K.isOutputData(output) ? K.output(output) : output;
	};
	K.ajax(options);
	return rs;
};

K.Message = function() {
	this.config = {};
	this.msg = function(msg, data) {
		this.config.msg = msg;
		if (data) {
			data = typeof data != "object" ? {
				value : data
			} : data;
			this.config.data = this.config.data || {};
			K.extend(this.config.data, data);
		}
		return this;
	};
	this.mtype = function(mtype) {
		this.config.mtype = mtype;
		return this;
	};
	this.lh = function(lh) {
		this.config.lh = lh;
		return this;
	};
	this.ls = function(ls) {
		this.config.ls = ls;
		return this;
	};
	this.el = function(el) {
		this.config.el = el;
		return this;
	};
	this.error = function(msg) {
		if (msg) {
			this.msg(msg);
		}
		this.mtype("error");
		return this;
	};
	this.show = function(el) {
		this.config.el = el || this.config.el;
		if (this.config.el) {
			if (this.config.data && Ext && Ext.Template) {
				var template = new Ext.Template(this.config.msg);
				this.config.msg = template.applyTemplate(this.config.data);
			}
			K.msg(this.config);
		}
		return this;
	};
};
K.m = function(msg, data) {
	var m = new K.Message();
	m.msg(msg, data);
	return m;
};
// error
K.err = function(msg, el) {
	K.msg({
		el : el,
		msg : msg,
		mtype : "error"
	});
};
K.noright = function(msg, el) {
	el = el || msg;
	K.msg({
		el : el,
		msg : arguments.length == 2 ? msg : "您无权进行当前操作",
		mtype : "error"
	});
};
// msg
K.msg = function(config, el) {
	var msg = null;
	if (!config) {
		msg = "";
		el = document.body;
	} else if (arguments.length == 2) {
		msg = config;
	} else if (typeof config == "string") {
		msg = config;
	} else {
		msg = config.msg;
	}

	el = el || config.el;
	if (!el) {
		el = document.body;
	} else {
		if (el.getEl && el.getEl().dom) {
			el = el.getEl().dom;
		} else if (el.getAttributeNS) {
			el = el.dom;
		}
	}
	var $el = (el instanceof $) ? el : $(el), pd = 5;
	var css = {
		background : config.mtype === "error" ? "#e6594e" : "green",
		// width : "auto;",
		"font-size" : "12px",
		"z-index" : 9999999999,
		position : "absolute",
		"text-align" : "center",
		"padding-left" : 3,
		"padding-right" : 3,
		"padding-top" : pd,
		"padding-bottom" : pd,
		"display" : "none",
		color : "#fff"
	};

	var a = $("<div>").css(css).html(msg);
	if (config.isout !== false) {
		var box = $el.offset(), left = box.left, top = box.top;
		a.appendTo(document.body);
		top = box.top - a.height() - 2 * pd, top = top < 0 ? 0 : top;
		a.css("left", left + ($el.width() - a.width()) / 2).css("top", top);
	} else {
		$el.children(":first").before(a);
		a.css("left", ($el.width() - a.width()) / 2);
	}
	var ls = config.ls || 0, lh = config.lh || 2000;
	if (ls) {
		setTimeout(function() {
			a.fadeS();
		}, ls);
	} else {
		a.show();
	}
	lh += ls;
	setTimeout(function() {
		a.fadeOut();
	}, lh);
	return;
};
K.POM = K.printObjectMsg = function(o) {
	alert(K.getObjectMsg(o));
};
K.emptyFn = function() {
};
window.k = K;

$(function() {
	if ($.validator) {
		$.validator.setDefaults({
			success : function(label) {
				label.addClass("checked");
			}
		});
	}

	if ($.ajaxSettings) {
		$.ajaxSettings.success = function(txt) {
			var output = K.createOutput(txt);
			if (!output.showError()) {
			}
		};
		$.ajaxSettings.error = function(a, b, c) {
			alert([ "请求失败", "地址：" + this.url ].join("\n"));
		};
	}
});